package com.niodata.md.rdb.crawler;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;

/**
 * datasource info.
 */
public class DataSourceInfo {

  private static final Map<String, String> defaultDrivers = new HashMap<>();

  static {
    defaultDrivers.put("mysql", "com.mysql.cj.jdbc.Driver");
    defaultDrivers.put("mariadb", "org.mariadb.jdbc.Driver");
    defaultDrivers.put("postgresql", "org.postgresql.Driver");
    defaultDrivers.put("oracle", "oracle.jdbc.driver.OracleDriver");
    defaultDrivers.put("sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver");
    defaultDrivers.put("doris", "com.mysql.cj.jdbc.Driver");
    defaultDrivers.put("presto", "com.facebook.presto.jdbc.PrestoDriver");
  }

  private final DataSourceConfig config;


  /**
   * constructor.
   *
   * @param config datasource config
   */
  public DataSourceInfo(DataSourceConfig config) {
    this.config = config;
  }

  /**
   * get config.
   *
   * @return config
   */
  public DataSourceConfig getConfig() {
    return this.config;
  }

  /**
   * get underlying database category.
   *
   * @return database category
   */
  public String getDbCategory() {
    return config.getDbCategory();
  }

  /**
   * get connection with default schema and db name.
   *
   * @return java.sql.Connection
   * @throws Exception sqlException
   */
  public Connection getConnection() throws Exception {
    return getConnection(null, null);
  }


  /**
   * get connection with default schema and db name.
   *
   * @return java.sql.Connection
   * @throws Exception sqlException
   */
  public Connection getConnection(String dbName) throws Exception {
    return getConnection(dbName, null);
  }


  /**
   * create new connection.
   *
   * @param dbName db name
   * @param schema schema name
   * @return java.sql.Connection
   * @throws Exception sqlException
   */
  public Connection getConnection(String dbName, String schema) throws Exception {
    if (schema == null) {
      schema = "";
    }
    String database = dbName;
    if (database == null || database.isEmpty()) {
      database = config.getDatabase();
    }
    if (database == null) {
      database = "";
    }
    String driver = config.getDriverClass();
    String category = this.config.getDbCategory();
    if (driver == null || driver.isEmpty()) {
      driver = defaultDrivers.get(category);
    }

    try {
      Class.forName(driver);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
    String user = config.getUser();
    String password = config.getPassword();
    String server = config.getServer();
    int port = config.getPort();
    String properties = config.getConnectionOptions();
    if (properties == null) {
      properties = "";
    }
    String url = "";
    String catalog = config.getCatalog();
    switch (category) {
      case "mysql", "doris":
        url = "jdbc:mysql://" + server + ":" + port + "/" + database + "?" + properties;
        break;
      case "mariadb":
        url = "jdbc:mariadb://" + server + ":" + port + "/" + database;
        break;
      case "postgresql":
        url = "jdbc:postgresql://" + server + ":" + port + "/" + database;
        break;
      case "oracle":
        url = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
        break;
      case "sqlserver":
        if (database != null && !database.isEmpty()) {
          url = "jdbc:sqlserver://" + server + ":" + port + ";databaseName=" + database;
        } else {
          url = "jdbc:sqlserver://" + server + ":" + port;
        }
        url = url + ";" + properties;
        break;
      case "db2":
        break;
      case "h2":
        break;
      case "hive":
        break;
      case "presto":
        url = "jdbc:presto://" + server + ":" + port + "/";
        if (!catalog.isEmpty()) {
          url = url + catalog;
          if (!schema.isEmpty()) {
            url = url + "/" + schema;
            if (!database.isEmpty()) {
              url = url + "/" + database;
            }
          }
        }
        break;
      default:
        break;
    }
    Connection connection = DriverManager.getConnection(url, user, password);
    return connection;
  }

}
